package utils

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"strings"
)

type TaskItem struct {
	Id    string
	Date  string
	Name  string
	Desc  string
	State string
}

func TaskEncrypter(dataLine string) string {
	data := strings.SplitN(dataLine, ", ", 2)
	crypted := EncryptByAES([]byte(data[1]), []byte(data[0][10:]))
	return data[0] + "&" + crypted
}

func TaskDecrypter(dataLine string) string {
	data := strings.Split(dataLine, "&")
	crypted := DecryptByAES(data[1], []byte(data[0][10:]))
	return data[0] + ", " + string(crypted)
}

func TaskReader() (taskList []TaskItem) {
	fp, err := os.OpenFile(DataFile, os.O_CREATE|os.O_RDONLY, 0666)
	Must(err)
	defer func() { Must(fp.Close()) }()
	reader := bufio.NewReader(fp)
	for {
		line, err := reader.ReadString('\n')
		if err == io.EOF {
			break
		}
		line = TaskDecrypter(line)
		line = strings.TrimSuffix(line, "\r\n")
		data := strings.Split(line, ", ")
		if len(data) < 5 {
			continue
		}
		taskList = append(taskList, TaskItem{
			Id:    data[0],
			Date:  data[1],
			Name:  data[2],
			Desc:  data[3],
			State: data[4],
		})
	}
	return
}

func QueryTaskById(id string) (task TaskItem) {
	for _, item := range TaskReader() {
		if item.Id == id {
			return item
		}
	}
	return
}

func QueryTasksByState(state string) (taskList []TaskItem) {
	for _, item := range TaskReader() {
		if item.State == state {
			taskList = append(taskList, item)
		}
	}
	return
}

func CheckDuplicateTask(task TaskItem) bool {
	for _, item := range TaskReader() {
		if item.State == task.State {
			if item.Name == task.Name && item.Desc == task.Desc {
				return true
			}
		}
	}
	return false
}

func TaskWriter(task TaskItem) {
	fp, err := os.OpenFile(DataFile, os.O_CREATE|os.O_APPEND, 0666)
	Must(err)
	defer func() { Must(fp.Close()) }()
	writer := bufio.NewWriter(fp)
	line := fmt.Sprintf(TaskLine, task.Id, task.Date, task.Name, task.Desc, task.State)
	line = TaskEncrypter(line)
	_, err = writer.WriteString(line + "\r\n")
	Must(err)
	Must(writer.Flush())
}

func TaskRewriter(task TaskItem) {
	tasks := TaskReader()
	Must(os.Truncate(DataFile, 0))
	for _, item := range tasks {
		if item.Id == task.Id {
			item = task
		}
		TaskWriter(item)
	}
}
